#ifndef __WIDGET_H__
#define __WIDGET_H__

#include <SDL.h>
#include "SDLControls.h"

#define DEFAULT_BG_COLOR_R 0x00
#define DEFAULT_BG_COLOR_G 0x00
#define DEFAULT_BG_COLOR_B 0x00

//necesario para resolver le dependencia circular entre SDLControls y Widget
class Widget;

typedef void (*CLICK_HANDLER_FUNC)(Widget* widget, const SDL_Event& event);
typedef void (*MOUSE_IN_HANDLER_FUNC)(Widget* widget, const SDL_Event& event);
typedef void (*MOUSE_OUT_HANDLER_FUNC)(Widget* widget, const SDL_Event& event);
typedef void (*KEY_DOWN_HANDLER_FUNC)(Widget* widget, const SDL_Event& event);
typedef void (*FOCUS_HANDLER_FUNC)(Widget* widget, const SDL_Event& event);
typedef void (*LOST_FOCUS_HANDLER_FUNC)(Widget* widget, const SDL_Event& event);

/**
 * Clase padre de todos los controles, cabeza de la jerarquia de elementos de interfaz grafica (botones, combos, etc)
 */
class Widget{
	int height;
	int width;
	int x;
	int y;
	CLICK_HANDLER_FUNC clickHandlerFunc;
	MOUSE_IN_HANDLER_FUNC mouseInHandlerFunc;
	MOUSE_OUT_HANDLER_FUNC mouseOutHandlerFunc;
	KEY_DOWN_HANDLER_FUNC keyDownHandlerFunc;
	FOCUS_HANDLER_FUNC focusHandlerFunc;
	LOST_FOCUS_HANDLER_FUNC lostFocusHandlerFunc;
	int onScreenWidgetId;
	SDL_Color bgColor;

public:

	/**
	 * Inicializa el widget
	 */
	Widget(const int& width, const int& height);

	/**
	 * Inicializa el widget con dimensiones nulas
	 */
	Widget();

	/**
 	 * Devuelve la altura del widget
	 */
	int const getHeight();

	/**
	 * Establece la altura del widget
	 */
	void setHeight(const int& height);

	/**
 	 * Devuelve el ancho del width
	 */
	int const getWidth();

	/**
	 * Establece el ancho del widget
	 */
	void setWidth(const int& width);

	/**
	 * Devuelve la coordenada x
	 */
	int const getX();

	/**
	 * Establece la coordenada x
	 */
	void setX(const int& x);

	/**
	 * Devuelve la coordenada y
	 */
	int const getY();

	/**
	 * Establece la coordenada y
	 */
	void setY(const int& y);

	/**
	 * Establece la función a invocarse cuando el widget sea clickeado
	 */
	void setClickHandler(CLICK_HANDLER_FUNC clickHandlerFunc);

	/**
	 * Establece la función a invocarse cuando el mouse entre al area ocupada por el widget
	 */
	void setMouseInHandler(MOUSE_IN_HANDLER_FUNC mouseInHandlerFunc);

	/**
	 * Establece la función a invocarse cuando el mouse sale del area ocupada por el widget
	 */
	void setMouseOutHandler(MOUSE_OUT_HANDLER_FUNC mouseOutHandlerFunc);

	/**
	 * Establece la función a invocarse cuando se aprete una tecla y el widget este enfocado
	 */
	void setKeyDownHandler(KEY_DOWN_HANDLER_FUNC keyDownHandlerFunc);

	/**
	 * Establece la función a invocarse cuando el widget es "enfocado"
	 */
	void setFocusHandler(FOCUS_HANDLER_FUNC focusHandlerFunc);

	/**
	 * Establece la función a invocarse cuando el widget es "desenfocado"
	 */
	void setLostFocusHandler(LOST_FOCUS_HANDLER_FUNC lostFocusHandlerFunc);

	/**
 	 * Dibuja el widget en la pantalla
	 */
	void virtual draw(SDL_Surface* screen, const int& x, const int& y)=0;

	/**
	 * Dispara el evento asociado a un click del mouse
	 */
	virtual void click(const SDL_Event& event);

	/**
	 * Dispara el evento asociado con la entrada del mouse al area ocupada por el widget
	 */
	virtual void mouseIn(const SDL_Event& event);

	/**
	 * Dispara el evento asociado con la salida del mouse del area ocupada por el widget
	 */
	virtual void mouseOut(const SDL_Event& event);

	/**
	 * Dispara el evento asociado con el "tecleo" de una tecla
	 */
	virtual void keyDown(const SDL_Event& event);

	/**
	 * Dispara el evento asociado al "enfoque" del widget
	 */
	virtual void focus(const SDL_Event& event);

	/**
	 * Dispara el evento asociado la perdida del foco del widget
	 */
	virtual void lostFocus(const SDL_Event& event);

	/**
	 * Devuelve verdadero o falso dependiendo de si el widget puede contener otros widgets
	 */
	virtual bool isWidgetContainer();

	/**
	 * Devuelve verdadero o falso dependiendo de si el punto recibido pertenece o no al area que ocupa el widget
	 */
	bool includesPoint(const int& x, const int& y);

	/**
	 * Establece el identificador del widget
	 */
	void setOnScreenWidgetId(const int& onScreenWidgetId);

	/**
	 * Devuelve un identificador del widget
	 */
	int const getOnScreenWidgetId();

	/**
	 * Establece el color de fondo
	 */
	void setBGColor(const int& red, const int& green, const int& blue);

	/**
	 * Establece el color de fondo
	 */
	void setBGColor(const SDL_Color& color);

	/**
	 * Devuelve el color de fonto
	 */
	SDL_Color getBGColor();

	/**
	 * Devuelve true o false dependiendo de si tiene sentido que el widget gane y pierda el foco
	 */
	virtual bool isFocusable();

	virtual ~Widget();
};

#endif
